package top.javarem.medical.service.impl;

import org.apache.commons.lang3.RandomStringUtils;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RedissonClient;
import org.redisson.client.protocol.ScoredEntry;
import org.springframework.stereotype.Service;
import top.javarem.medical.common.context.BaseContext;
import top.javarem.medical.domain.dto.UserCreditRankDTO;
import top.javarem.medical.domain.po.PointsLog;
import top.javarem.medical.domain.po.User;
import top.javarem.medical.service.PointsLogService;
import top.javarem.medical.service.UserCreditService;
import top.javarem.medical.service.UserService;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 */
@Service
public class UserCreditServiceImpl implements UserCreditService {

    private static final String cacheKey = "USER_SCORE_RANK_KEY";

    @Resource
    private PointsLogService pointsLogService;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private UserService userService;

    @Override
    public boolean updateUserCredit(int totalScore) {

        Long userId = BaseContext.getCurrentId();
        PointsLog pointsLog = new PointsLog();
        pointsLog.setUserId(userId);
        pointsLog.setType("答题获取");
        pointsLog.setAmount(totalScore);
        pointsLog.setRelatedId(RandomStringUtils.randomNumeric(12));
        boolean save = pointsLogService.save(pointsLog);
        if (!save) {
            throw new RuntimeException("插入积分记录失败!");
        }
        // 1. 更新数据库
        boolean update = userService.lambdaUpdate()
                .setSql("points = points + " + totalScore)
                .eq(User::getId, pointsLog.getUserId())
                .update();
        if (!update) {
            throw new RuntimeException("更新用户积分失败");
        }

        // 2. 更新Redis排行榜
        RScoredSortedSet<Long> scoredSortedSet = redissonClient.<Long>getScoredSortedSet(cacheKey);
        scoredSortedSet.addScore(userId, totalScore);
        // 设置缓存过期时间为 24 小时
        scoredSortedSet.expire(24, TimeUnit.HOURS);
        return true;
    }

    //查询用户积分排名前10的用户信息
    @Override
    public List<UserCreditRankDTO> queryUserCreditRank() {

        RScoredSortedSet<Long> scoredSortedSet = redissonClient.<Long>getScoredSortedSet(cacheKey);
        Collection<ScoredEntry<Long>> top10 = scoredSortedSet.entryRangeReversed(0, 10);
        int rank = 1;
        List<UserCreditRankDTO> userCreditRankDTOList = new ArrayList<UserCreditRankDTO>();
        for (ScoredEntry<Long> entry : top10) {

            User user = userService.lambdaQuery()
                    .select(User::getNickname, User::getAvatar)
                    .eq(User::getId, entry.getValue())
                    .one();
            Double score = entry.getScore();


            userCreditRankDTOList.add(UserCreditRankDTO.builder()
                    .nickname(user.getNickname())
                    .avatar(user.getAvatar())
                    .credit(score.intValue())
                    .rank(rank)
                    .build());
            rank++;
        }
        return userCreditRankDTOList;
    }

}
